home *** CD-ROM | disk | FTP | other *** search
- From pacbell!ames!mailrus!cornell!rochester!bbn!bbn.com!rsalz Fri Jul 1 13:13:46 1988
- From: rsalz@bbn.com (Rich Salz)
- Newsgroups: comp.sources.unix
- Subject: v15i081: ARC (PC compression program), v5.21, Part05/05
- Message-ID: <969@fig.bbn.com>
- Date: 1 Jul 88 20:13:46 GMT
-
- Submitted-by: hyc@math.lsa.umich.edu
- Posting-number: Volume 15, Issue 81
- Archive-name: arc5.21/part05
-
- #--------------------------------CUT HERE-------------------------------------
- #! /bin/sh
- #
- # This is a shell archive. Save this into a file, edit it
- # and delete all lines above this comment. Then give this
- # file to sh by executing the command "sh file". The files
- # will be extracted into the current directory owned by
- # you with default permissions.
- #
- # The files contained herein are:
- #
- # -rw-r--r-- 1 hyc 11514 Jun 13 13:54 arcsqs.c
- # -rw-r--r-- 1 hyc 4680 Jun 13 00:43 arcsvc.c
- # -rw-r--r-- 1 hyc 1284 Apr 19 01:40 arctst.c
- # -rw-r--r-- 1 hyc 5347 Jun 18 03:13 arcunp.c
- # -rw-r--r-- 1 hyc 2484 Jun 2 16:28 arcusq.c
- # -rw-r--r-- 1 hyc 9032 Jun 13 13:56 dtime.c
- # -rw-r--r-- 1 hyc 7327 Apr 11 19:11 dtimep.lex
- # -rw-r--r-- 1 hyc 356 Apr 11 19:12 lexedit.sed
- # -rw-r--r-- 1 hyc 3713 Jun 13 13:59 lexstring.c
- # -rw-r--r-- 1 hyc 2241 Apr 11 19:13 libtws.3
- # -rw-r--r-- 1 hyc 9053 Jun 6 01:04 marc.c
- #
- echo 'x - arcsqs.c'
- if test -f arcsqs.c; then echo 'shar: not overwriting arcsqs.c'; else
- sed 's/^X//' << '________This_Is_The_END________' > arcsqs.c
- X/*
- X * $Header: arcsqs.c,v 1.2 88/06/01 16:31:39 hyc Locked $
- X */
- X
- X/* ARC - Archive utility - SQUASH
- X
- X(C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
- X
- X This is a quick hack to ARCLZW to make it handle squashed archives.
- X Dan Lanciani (ddl@harvard.*) July 87
- X
- X*/
- X
- X/*
- X * $Header: arcsqs.c,v 1.2 88/06/01 16:31:39 hyc Locked $
- X */
- X
- X#include <stdio.h>
- X#include "arc.h"
- X
- X#if MSDOS
- Xchar *setmem();
- X#else
- Xchar *memset();
- X#endif
- Xint getc_unp();
- Xvoid putc_pak(), putc_unp();
- Xstatic void putcode();
- X
- X/* definitions for the new dynamic Lempel-Zev crunching */
- X
- X#define BITS 13 /* maximum bits per code */
- X#define HSIZE 10007 /* 80% occupancy */
- X#define INIT_BITS 9 /* initial number of bits/code */
- Xstatic int n_bits; /* number of bits/code */
- Xstatic int maxcode; /* maximum code, given n_bits */
- X#define MAXCODE(n) ((1<<(n)) - 1) /* maximum code calculation */
- Xstatic int maxcodemax = 1 << BITS; /* largest possible code (+1) */
- X
- Xstatic unsigned char buf[BITS]; /* input/output buffer */
- X
- Xstatic unsigned char lmask[9] = /* left side masks */
- X{0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
- Xstatic unsigned char rmask[9] = /* right side masks */
- X{0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
- X
- Xstatic int offset; /* byte offset for code output */
- Xstatic long in_count; /* length of input */
- Xstatic long bytes_out; /* length of compressed output */
- Xstatic unsigned short ent;
- X
- Xlong htab[HSIZE]; /* hash code table (crunch) */
- Xunsigned short codetab[HSIZE]; /* string code table (crunch) */
- X
- Xstatic unsigned short *prefix = codetab; /* prefix code table (uncrunch) */
- Xstatic unsigned char *suffix=(unsigned char *)htab; /* suffix table (uncrunch) */
- Xstatic int free_ent; /* first unused entry */
- Xstatic int firstcmp; /* true at start of compression */
- Xunsigned char stack[HSIZE]; /* local push/pop stack */
- X
- X/*
- X * block compression parameters -- after all codes are used up,
- X * and compression rate changes, start over.
- X */
- X
- Xstatic int clear_flg;
- Xstatic long ratio;
- X#define CHECK_GAP 10000 /* ratio check interval */
- Xstatic long checkpoint;
- X
- X/*
- X * the next two codes should not be changed lightly, as they must not
- X * lie within the contiguous general code space.
- X */
- X#define FIRST 257 /* first free entry */
- X#define CLEAR 256 /* table clear output code */
- X
- Xstatic void
- Xcl_block(t) /* table clear for block compress */
- X FILE *t; /* our output file */
- X{
- X long rat;
- X
- X checkpoint = in_count + CHECK_GAP;
- X
- X if (in_count > 0x007fffffL) { /* shift will overflow */
- X rat = bytes_out >> 8;
- X if (rat == 0) /* Don't divide by zero */
- X rat = 0x7fffffffL;
- X else
- X rat = in_count / rat;
- X } else
- X rat = (in_count << 8) / bytes_out; /* 8 fractional bits */
- X
- X if (rat > ratio)
- X ratio = rat;
- X else {
- X ratio = 0;
- X setmem(htab, HSIZE * sizeof(long), 0xff);
- X free_ent = FIRST;
- X clear_flg = 1;
- X putcode(CLEAR, t);
- X }
- X}
- X
- X/*****************************************************************
- X *
- X * Output a given code.
- X * Inputs:
- X * code: A n_bits-bit integer. If == -1, then EOF. This assumes
- X * that n_bits =< (long)wordsize - 1.
- X * Outputs:
- X * Outputs code to the file.
- X * Assumptions:
- X * Chars are 8 bits long.
- X * Algorithm:
- X * Maintain a BITS character long buffer (so that 8 codes will
- X * fit in it exactly). When the buffer fills up empty it and start over.
- X */
- X
- Xstatic void
- Xputcode(code, t) /* output a code */
- X int code; /* code to output */
- X FILE *t; /* where to put it */
- X{
- X int r_off = offset; /* right offset */
- X int bits = n_bits; /* bits to go */
- X unsigned char *bp = buf; /* buffer pointer */
- X int n; /* index */
- X register int ztmp;
- X
- X if (code >= 0) { /* if a real code *//* Get to the first byte. */
- X bp += (r_off >> 3);
- X r_off &= 7;
- X
- X /*
- X * Since code is always >= 8 bits, only need to mask the
- X * first hunk on the left.
- X */
- X ztmp = (code << r_off) & lmask[r_off];
- X *bp = (*bp & rmask[r_off]) | ztmp;
- X bp++;
- X bits -= (8 - r_off);
- X code >>= (8 - r_off);
- X
- X /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
- X if (bits >= 8) {
- X *bp++ = code;
- X code >>= 8;
- X bits -= 8;
- X }
- X /* Last bits. */
- X if (bits)
- X *bp = code;
- X
- X offset += n_bits;
- X
- X if (offset == (n_bits << 3)) {
- X bp = buf;
- X bits = n_bits;
- X bytes_out += bits;
- X do
- X putc_pak(*bp++, t);
- X while (--bits);
- X offset = 0;
- X }
- X /*
- X * If the next entry is going to be too big for the code
- X * size, then increase it, if possible.
- X */
- X if (free_ent > maxcode || clear_flg > 0) { /* Write the whole
- X * buffer, because the
- X * input side won't
- X * discover the size
- X * increase until after
- X * it has read it. */
- X if (offset > 0) {
- X bp = buf; /* reset pointer for writing */
- X bytes_out += n = n_bits;
- X while (n--)
- X putc_pak(*bp++, t);
- X }
- X offset = 0;
- X
- X if (clear_flg) { /* reset if clearing */
- X maxcode = MAXCODE(n_bits = INIT_BITS);
- X clear_flg = 0;
- X } else {/* else use more bits */
- X n_bits++;
- X if (n_bits == BITS)
- X maxcode = maxcodemax;
- X else
- X maxcode = MAXCODE(n_bits);
- X }
- X }
- X } else { /* dump the buffer on EOF */
- X bytes_out += n = (offset + 7) / 8;
- X
- X if (offset > 0)
- X while (n--)
- X putc_pak(*bp++, t);
- X offset = 0;
- X }
- X}
- X
- X/*****************************************************************
- X *
- X * Read one code from the standard input. If EOF, return -1.
- X * Inputs:
- X * cmpin
- X * Outputs:
- X * code or -1 is returned.
- X */
- X
- Xstatic int
- Xgetcode(f) /* get a code */
- X FILE *f; /* file to get from */
- X{
- X int code;
- X static int offset = 0, size = 0;
- X int r_off, bits;
- X unsigned char *bp = buf;
- X
- X if (clear_flg > 0 || offset >= size || free_ent > maxcode) {
- X /* If the next entry will be too big for the current code
- X * size, then we must increase the size. This implies reading
- X * a new buffer full, too. */
- X if (free_ent > maxcode) {
- X n_bits++;
- X if (n_bits == BITS)
- X maxcode = maxcodemax; /* won't get any bigger
- X * now */
- X else
- X maxcode = MAXCODE(n_bits);
- X }
- X if (clear_flg > 0) {
- X maxcode = MAXCODE(n_bits = INIT_BITS);
- X clear_flg = 0;
- X }
- X for (size = 0; size < n_bits; size++) {
- X if ((code = getc_unp(f)) == EOF)
- X break;
- X else
- X buf[size] = code;
- X }
- X if (size <= 0)
- X return -1; /* end of file */
- X
- X offset = 0;
- X /* Round size down to integral number of codes */
- X size = (size << 3) - (n_bits - 1);
- X }
- X r_off = offset;
- X bits = n_bits;
- X
- X /*
- X * Get to the first byte.
- X */
- X bp += (r_off >> 3);
- X r_off &= 7;
- X
- X /* Get first part (low order bits) */
- X code = (*bp++ >> r_off);
- X bits -= 8 - r_off;
- X r_off = 8 - r_off; /* now, offset into code word */
- X
- X /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
- X if (bits >= 8) {
- X code |= *bp++ << r_off;
- X r_off += 8;
- X bits -= 8;
- X }
- X /* high order bits. */
- X code |= (*bp & rmask[bits]) << r_off;
- X offset += n_bits;
- X
- X return code;
- X}
- X
- X/*
- X * compress a file
- X *
- X * Algorithm: use open addressing double hashing (no chaining) on the
- X * prefix code / next character combination. We do a variant of Knuth's
- X * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
- X * secondary probe. Here, the modular division first probe is gives way
- X * to a faster exclusive-or manipulation. Also do block compression with
- X * an adaptive reset, where the code table is cleared when the compression
- X * ratio decreases, but after the table fills. The variable-length output
- X * codes are re-sized at this point, and a special CLEAR code is generated
- X * for the decompressor.
- X */
- X
- Xvoid
- Xsqinit_cm() /* initialize for compression */
- X{
- X offset = 0;
- X bytes_out = 0;
- X clear_flg = 0;
- X ratio = 0;
- X in_count = 1;
- X checkpoint = CHECK_GAP;
- X maxcode = MAXCODE(n_bits = INIT_BITS);
- X free_ent = FIRST;
- X setmem(htab, HSIZE * sizeof(long), 0xff);
- X n_bits = INIT_BITS; /* set starting code size */
- X
- X firstcmp = 1; /* next byte will be first */
- X}
- X
- Xvoid
- Xsqputc_cm(c, t) /* compress a character */
- X unsigned char c; /* character to compress */
- X FILE *t; /* where to put it */
- X{
- X static long fcode;
- X static int hshift;
- X int i;
- X int disp;
- X
- X if (firstcmp) { /* special case for first byte */
- X ent = c; /* remember first byte */
- X
- X hshift = 0;
- X for (fcode = (long) HSIZE; fcode < 65536L; fcode *= 2L)
- X hshift++;
- X hshift = 8 - hshift; /* set hash code range bund */
- X
- X firstcmp = 0; /* no longer first */
- X return;
- X }
- X in_count++;
- X fcode = (long) (((long) c << BITS) + ent);
- X i = (c << hshift) ^ ent;/* xor hashing */
- X
- X if (htab[i] == fcode) {
- X ent = codetab[i];
- X return;
- X } else if (htab[i] < 0) /* empty slot */
- X goto nomatch;
- X disp = HSIZE - i; /* secondary hash (after G.Knott) */
- X if (i == 0)
- X disp = 1;
- X
- Xprobe:
- X if ((i -= disp) < 0)
- X i += HSIZE;
- X
- X if (htab[i] == fcode) {
- X ent = codetab[i];
- X return;
- X }
- X if (htab[i] > 0)
- X goto probe;
- X
- Xnomatch:
- X putcode(ent, t);
- X ent = c;
- X if (free_ent < maxcodemax) {
- X codetab[i] = free_ent++; /* code -> hashtable */
- X htab[i] = fcode;
- X } else if ((long) in_count >= checkpoint)
- X cl_block(t);
- X}
- X
- Xlong
- Xsqpred_cm(t) /* finish compressing a file */
- X FILE *t; /* where to put it */
- X{
- X putcode(ent, t); /* put out the final code */
- X putcode(-1, t); /* tell output we are done */
- X
- X return bytes_out; /* say how big it got */
- X}
- X
- X/*
- X * Decompress a file. This routine adapts to the codes in the file
- X * building the string table on-the-fly; requiring no table to be stored
- X * in the compressed file. The tables used herein are shared with those of
- X * the compress() routine. See the definitions above.
- X */
- X
- Xvoid
- Xsqdecomp(f, t) /* decompress a file */
- X FILE *f; /* file to read codes from */
- X FILE *t; /* file to write text to */
- X{
- X unsigned char *stackp;
- X int finchar;
- X int code, oldcode, incode;
- X
- X n_bits = INIT_BITS; /* set starting code size */
- X clear_flg = 0;
- X
- X /*
- X * As above, initialize the first 256 entries in the table.
- X */
- X maxcode = MAXCODE(n_bits = INIT_BITS);
- X for (code = 255; code >= 0; code--) {
- X prefix[code] = 0;
- X suffix[code] = (unsigned char) code;
- X }
- X free_ent = FIRST;
- X
- X finchar = oldcode = getcode(f);
- X if (oldcode == -1) /* EOF already? */
- X return; /* Get out of here */
- X putc_unp((char) finchar, t); /* first code must be 8 bits=char */
- X stackp = stack;
- X
- X while ((code = getcode(f)) > -1) {
- X if (code == CLEAR) {
- X for (code = 255; code >= 0; code--)
- X prefix[code] = 0;
- X clear_flg = 1;
- X free_ent = FIRST - 1;
- X if ((code = getcode(f)) == -1) /* O, untimely death! */
- X break;
- X }
- X incode = code;
- X /*
- X * Special case for KwKwK string.
- X */
- X if (code >= free_ent) {
- X if (code > free_ent) {
- X if (warn) {
- X printf("Corrupted compressed file.\n");
- X printf("Invalid code %d when max is %d.\n",
- X code, free_ent);
- X }
- X nerrs++;
- X return;
- X }
- X *stackp++ = finchar;
- X code = oldcode;
- X }
- X /*
- X * Generate output characters in reverse order
- X */
- X while (code >= 256) {
- X *stackp++ = suffix[code];
- X code = prefix[code];
- X }
- X *stackp++ = finchar = suffix[code];
- X
- X /*
- X * And put them out in forward order
- X */
- X do
- X putc_unp(*--stackp, t);
- X while (stackp > stack);
- X
- X /*
- X * Generate the new entry.
- X */
- X if ((code = free_ent) < maxcodemax) {
- X prefix[code] = (unsigned short) oldcode;
- X suffix[code] = finchar;
- X free_ent = code + 1;
- X }
- X /*
- X * Remember previous code.
- X */
- X oldcode = incode;
- X }
- X}
- ________This_Is_The_END________
- if test `wc -c < arcsqs.c` -ne 11514; then
- echo 'shar: arcsqs.c was damaged during transit (should have been 11514 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - arcsvc.c'
- if test -f arcsvc.c; then echo 'shar: not overwriting arcsvc.c'; else
- sed 's/^X//' << '________This_Is_The_END________' > arcsvc.c
- X/*
- X * $Header: arcsvc.c,v 1.8 88/06/13 00:42:59 hyc Locked $
- X */
- X
- X/* ARC - Archive utility - ARCSVC
- X
- X Version 2.23, created on 04/22/87 at 13:10:10
- X
- X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED
- X
- X By: Thom Henderson
- X
- X Description:
- X This file contains service routines needed to maintain an archive.
- X
- X Language:
- X Computer Innovations Optimizing C86
- X*/
- X#include <stdio.h>
- X#include "arc.h"
- X#if MTS
- X#include <mts.h>
- X#endif
- X
- Xvoid abort(), setstamp();
- Xint unlink();
- X
- Xvoid
- Xopenarc(chg) /* open archive */
- X int chg; /* true to open for changes */
- X{
- X FILE *fopen();/* file opener */
- X
- X if (!(arc = fopen(arcname, "rb"))) {
- X if (chg) {
- X if (note)
- X printf("Creating new archive: %s\n", arcname);
- X }
- X else
- X abort("Archive not found: %s", arcname);
- X }
- X#if MTS /* allow reading archives of max MTS record length */
- X else {
- X char *buffer, *malloc();
- X int inlen;
- X struct GDDSECT *region;
- X
- X region=gdinfo(arc->_fd);
- X inlen=region->GDINLEN;
- X buffer=malloc(inlen);
- X setbuf(arc, buffer);
- X arc->_bufsiz=inlen;
- X }
- X#endif
- X if (chg) { /* if opening for changes */
- X if (!(new = fopen(newname, "wb")))
- X abort("Cannot create archive copy: %s", newname);
- X
- X changing = chg; /* note if open for changes */
- X }
- X}
- X
- Xvoid
- Xclosearc(chg) /* close an archive */
- X int chg; /* true if archive was changed */
- X{
- X if (arc) { /* if we had an initial archive */
- X fclose(arc);
- X if (kludge) /* kludge to update timestamp */
- X#if !MTS
- X setstamp(arcname, olddate, oldtime);
- X#endif
- X }
- X if (chg) { /* if things have changed */
- X fclose(new); /* close the new copy */
- X if (arc) { /* if we had an original archive */
- X if (keepbak) { /* if a backup is wanted */
- X unlink(bakname); /* erase any old copies */
- X if (move(arcname, bakname))
- X abort("Cannot rename %s to %s", arcname, bakname);
- X printf("Keeping backup archive: %s\n", bakname);
- X } else if (unlink(arcname))
- X abort("Cannot delete old archive: %s", arcname);
- X }
- X if (move(newname, arcname))
- X abort("Cannot move %s to %s", newname, arcname);
- X#if !MTS
- X setstamp(arcname, arcdate, arctime);
- X#endif
- X }
- X}
- X
- X/*
- X * CRC computation logic
- X *
- X * The logic for this method of calculating the CRC 16 bit polynomial is taken
- X * from an article by David Schwaderer in the April 1985 issue of PC Tech
- X * Journal.
- X */
- X
- Xstatic short crctab[] = /* CRC lookup table */
- X{
- X 0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
- X 0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
- X 0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
- X 0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
- X 0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
- X 0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
- X 0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
- X 0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
- X 0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
- X 0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
- X 0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
- X 0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
- X 0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
- X 0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
- X 0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
- X 0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
- X 0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
- X 0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
- X 0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
- X 0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
- X 0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
- X 0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
- X 0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
- X 0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
- X 0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
- X 0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
- X 0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
- X 0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
- X 0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
- X 0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
- X 0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
- X 0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
- X};
- X
- Xint
- Xaddcrc(crc, c) /* update a CRC check */
- X int crc; /* running CRC value */
- X unsigned char c; /* character to add */
- X{
- X return ((crc >> 8) & 0x00ff) ^ crctab[(crc ^ c) & 0x00ff];
- X}
- ________This_Is_The_END________
- if test `wc -c < arcsvc.c` -ne 4680; then
- echo 'shar: arcsvc.c was damaged during transit (should have been 4680 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - arctst.c'
- if test -f arctst.c; then echo 'shar: not overwriting arctst.c'; else
- sed 's/^X//' << '________This_Is_The_END________' > arctst.c
- X/*
- X * $Header: arctst.c,v 1.4 88/04/19 01:40:28 hyc Exp $
- X */
- X
- X/*
- X * ARC - Archive utility - ARCTST
- X *
- X * Version 2.12, created on 02/03/86 at 23:00:40
- X *
- X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
- X *
- X * By: Thom Henderson
- X *
- X * Description: This file contains the routines used to test archive integrity.
- X *
- X * Language: Computer Innovations Optimizing C86
- X */
- X#include <stdio.h>
- X#include "arc.h"
- X
- Xvoid openarc();
- Xint readhdr(), unpack();
- X
- Xvoid
- Xtstarc()
- X{ /* test integrity of an archive */
- X struct heads hdr; /* file header */
- X long arcsize, ftell(); /* archive size */
- X
- X openarc(0); /* open archive for reading */
- X fseek(arc, 0L, 2); /* move to end of archive */
- X arcsize = ftell(arc); /* see how big it is */
- X fseek(arc, 0L, 0); /* return to top of archive */
- X
- X while (readhdr(&hdr, arc)) {
- X if (ftell(arc) + hdr.size > arcsize) {
- X printf("Archive truncated in file %s\n", hdr.name);
- X nerrs++;
- X break;
- X } else {
- X printf("Testing file: %-12s ", hdr.name);
- X fflush(stdout);
- X if (unpack(arc, NULL, &hdr))
- X nerrs++;
- X else
- X printf("okay\n");
- X }
- X }
- X
- X if (nerrs < 1)
- X printf("No errors detected\n");
- X else if (nerrs == 1)
- X printf("One error detected\n");
- X else
- X printf("%d errors detected\n", nerrs);
- X}
- ________This_Is_The_END________
- if test `wc -c < arctst.c` -ne 1284; then
- echo 'shar: arctst.c was damaged during transit (should have been 1284 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - arcunp.c'
- if test -f arcunp.c; then echo 'shar: not overwriting arcunp.c'; else
- sed 's/^X//' << '________This_Is_The_END________' > arcunp.c
- X/*
- X * $Header: arcunp.c,v 1.7 88/06/18 03:12:36 hyc Locked $
- X */
- X
- X/*
- X * ARC - Archive utility - ARCUNP
- X *
- X * Version 3.17, created on 02/13/86 at 10:20:08
- X *
- X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
- X *
- X * By: Thom Henderson
- X *
- X * Description: This file contains the routines used to expand a file when
- X * taking it out of an archive.
- X *
- X * Language: Computer Innovations Optimizing C86
- X */
- X#include <stdio.h>
- X#include "arc.h"
- X#if MTS
- X#include <ctype.h>
- X#endif
- X
- Xvoid setcode(), init_usq(), init_ucr(), decomp(), sqdecomp();
- Xvoid abort(), putc_tst();
- Xint getc_usq(), getc_ucr(), addcrc();
- X
- X/* stuff for repeat unpacking */
- X
- X#define DLE 0x90 /* repeat byte flag */
- X
- Xstatic int state; /* repeat unpacking state */
- X
- X/* repeat unpacking states */
- X
- X#define NOHIST 0 /* no relevant history */
- X#define INREP 1 /* sending a repeated value */
- X
- Xstatic short crcval; /* CRC check value */
- Xstatic long size; /* bytes to read */
- X#if !DOS
- Xstatic int gotcr; /* got a carriage return? */
- X#endif
- X
- Xint
- Xunpack(f, t, hdr) /* unpack an archive entry */
- X FILE *f, *t; /* source, destination */
- X struct heads *hdr; /* pointer to file header data */
- X{
- X int c; /* one char of stream */
- X void putc_unp();
- X void putc_ncr();
- X int getc_unp();
- X
- X /* setups common to all methods */
- X#if !DOS
- X gotcr = 0;
- X#endif
- X crcval = 0; /* reset CRC check value */
- X size = hdr->size; /* set input byte counter */
- X state = NOHIST; /* initial repeat unpacking state */
- X setcode(); /* set up for decoding */
- X
- X /* use whatever method is appropriate */
- X
- X switch (hdrver) { /* choose proper unpack method */
- X case 1: /* standard packing */
- X case 2:
- X while ((c = getc_unp(f)) != EOF)
- X putc_unp((char) c, t);
- X break;
- X
- X case 3: /* non-repeat packing */
- X while ((c = getc_unp(f)) != EOF)
- X putc_ncr((unsigned char) c, t);
- X break;
- X
- X case 4: /* Huffman squeezing */
- X init_usq(f);
- X while ((c = getc_usq(f)) != EOF)
- X putc_ncr((unsigned char) c, t);
- X break;
- X
- X case 5: /* Lempel-Zev compression */
- X init_ucr(0);
- X while ((c = getc_ucr(f)) != EOF)
- X putc_unp((char) c, t);
- X break;
- X
- X case 6: /* Lempel-Zev plus non-repeat */
- X init_ucr(0);
- X while ((c = getc_ucr(f)) != EOF)
- X putc_ncr((unsigned char) c, t);
- X break;
- X
- X case 7: /* L-Z plus ncr with new hash */
- X init_ucr(1);
- X while ((c = getc_ucr(f)) != EOF)
- X putc_ncr((unsigned char) c, t);
- X break;
- X
- X case 8: /* dynamic Lempel-Zev */
- X decomp(f, t);
- X break;
- X
- X case 9: /* Squashing */
- X sqdecomp(f, t);
- X break;
- X
- X default: /* unknown method */
- X if (warn) {
- X printf("I don't know how to unpack file %s\n", hdr->name);
- X printf("I think you need a newer version of ARC\n");
- X nerrs++;
- X }
- X fseek(f, hdr->size, 1); /* skip over bad file */
- X return 1; /* note defective file */
- X }
- X
- X /* cleanups common to all methods */
- X
- X if (crcval != hdr->crc) {
- X if (warn || kludge) {
- X printf("WARNING: File %s fails CRC check\n", hdr->name);
- X nerrs++;
- X }
- X return 1; /* note defective file */
- X }
- X return 0; /* file is okay */
- X}
- X
- X/*
- X * This routine is used to put bytes in the output file. It also performs
- X * various housekeeping functions, such as maintaining the CRC check value.
- X */
- X
- Xvoid
- Xputc_unp(c, t) /* output an unpacked byte */
- X char c; /* byte to output */
- X FILE *t; /* file to output to */
- X{
- X crcval = addcrc(crcval, c); /* update the CRC check value */
- X#if MTS
- X if (!image)
- X atoe(&c, 1);
- X#endif
- X#if DOS
- X putc_tst(c, t);
- X#else
- X if (image)
- X putc_tst(c, t);
- X else {
- X if (gotcr) {
- X gotcr = 0;
- X if (c != '\n')
- X putc_tst('\r', t);
- X }
- X if (c == '\r')
- X gotcr = 1;
- X else
- X putc_tst(c, t);
- X }
- X#endif
- X}
- X
- X/*
- X * This routine is used to decode non-repeat compression. Bytes are passed
- X * one at a time in coded format, and are written out uncoded. The data is
- X * stored normally, except that runs of more than two characters are
- X * represented as:
- X *
- X * <char> <DLE> <count>
- X *
- X * With a special case that a count of zero indicates a DLE as data, not as a
- X * repeat marker.
- X */
- X
- Xvoid
- Xputc_ncr(c, t) /* put NCR coded bytes */
- X unsigned char c; /* next byte of stream */
- X FILE *t; /* file to receive data */
- X{
- X static int lastc; /* last character seen */
- X
- X switch (state) { /* action depends on our state */
- X case NOHIST: /* no previous history */
- X if (c == DLE) /* if starting a series */
- X state = INREP; /* then remember it next time */
- X else
- X putc_unp(lastc = c, t); /* else nothing unusual */
- X return;
- X
- X case INREP: /* in a repeat */
- X if (c) /* if count is nonzero */
- X while (--c) /* then repeatedly ... */
- X putc_unp(lastc, t); /* ... output the byte */
- X else
- X putc_unp(DLE, t); /* else output DLE as data */
- X state = NOHIST; /* back to no history */
- X return;
- X
- X default:
- X abort("Bad NCR unpacking state (%d)", state);
- X }
- X}
- X
- X/*
- X * This routine provides low-level byte input from an archive. This routine
- X * MUST be used, as end-of-file is simulated at the end of the archive entry.
- X */
- X
- Xint
- Xgetc_unp(f) /* get a byte from an archive */
- X FILE *f; /* archive file to read */
- X{
- X register int xx;
- X unsigned char code();
- X
- X if (!size) /* if no data left */
- X return EOF; /* then pretend end of file */
- X
- X size--; /* deduct from input counter */
- X xx = getc(f);
- X return code(xx); /* and return next decoded byte */
- X}
- ________This_Is_The_END________
- if test `wc -c < arcunp.c` -ne 5347; then
- echo 'shar: arcunp.c was damaged during transit (should have been 5347 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - arcusq.c'
- if test -f arcusq.c; then echo 'shar: not overwriting arcusq.c'; else
- sed 's/^X//' << '________This_Is_The_END________' > arcusq.c
- X/*
- X * $Header: arcusq.c,v 1.2 88/06/02 16:27:44 hyc Locked $
- X */
- X
- X/*
- X * ARC - Archive utility - ARCUSQ
- X *
- X * Version 3.14, created on 07/25/86 at 13:04:19
- X *
- X * (C) COPYRIGHT 1985 by System Enhancement Associates; ALL RIGHTS RESERVED
- X *
- X * By: Thom Henderson
- X *
- X * Description: This file contains the routines used to expand a file which was
- X * packed using Huffman squeezing.
- X *
- X * Most of this code is taken from an USQ program by Richard Greenlaw, which was
- X * adapted to CI-C86 by Robert J. Beilstein.
- X *
- X * Language: Computer Innovations Optimizing C86
- X */
- X#include <stdio.h>
- X#include "arc.h"
- X
- Xvoid abort();
- Xint getc_unp();
- X
- X/* stuff for Huffman unsqueezing */
- X
- X#define ERROR (-1)
- X
- X#define SPEOF 256 /* special endfile token */
- X#define NUMVALS 257 /* 256 data values plus SPEOF */
- X
- Xextern struct nd { /* decoding tree */
- X int child[2]; /* left, right */
- X} node[NUMVALS]; /* use large buffer */
- X
- Xstatic int bpos; /* last bit position read */
- Xstatic int curin; /* last byte value read */
- Xstatic int numnodes; /* number of nodes in decode tree */
- X
- Xstatic short
- Xget_int(f) /* get a 16bit integer */
- X FILE *f; /* file to get it from */
- X{
- X int i,j;
- X i = getc_unp(f);
- X j = getc_unp(f) << 8;
- X return (i | j) & 0xFFFF;
- X}
- X
- Xvoid
- Xinit_usq(f) /* initialize Huffman unsqueezing */
- X FILE *f; /* file containing squeezed data */
- X{
- X int i; /* node index */
- X
- X bpos = 99; /* force initial read */
- X
- X numnodes = get_int(f);
- X
- X if (numnodes < 0 || numnodes >= NUMVALS)
- X abort("File has an invalid decode tree");
- X
- X /* initialize for possible empty tree (SPEOF only) */
- X
- X node[0].child[0] = -(SPEOF + 1);
- X node[0].child[1] = -(SPEOF + 1);
- X
- X for (i = 0; i < numnodes; ++i) { /* get decoding tree from
- X * file */
- X node[i].child[0] = get_int(f);
- X node[i].child[1] = get_int(f);
- X }
- X}
- X
- Xint
- Xgetc_usq(f) /* get byte from squeezed file */
- X FILE *f; /* file containing squeezed data */
- X{
- X int i; /* tree index */
- X
- X /* follow bit stream in tree to a leaf */
- X
- X for (i = 0; i >= 0;) { /* work down(up?) from root */
- X if (++bpos > 7) {
- X if ((curin = getc_unp(f)) == ERROR)
- X return (ERROR);
- X bpos = 0;
- X
- X /* move a level deeper in tree */
- X i = node[i].child[1 & curin];
- X } else
- X i = node[i].child[1 & (curin >>= 1)];
- X }
- X
- X /* decode fake node index to original data value */
- X
- X i = -(i + 1);
- X
- X /* decode special endfile token to normal EOF */
- X
- X i = (i == SPEOF) ? EOF : i;
- X return i;
- X}
- ________This_Is_The_END________
- if test `wc -c < arcusq.c` -ne 2484; then
- echo 'shar: arcusq.c was damaged during transit (should have been 2484 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - dtime.c'
- if test -f dtime.c; then echo 'shar: not overwriting dtime.c'; else
- sed 's/^X//' << '________This_Is_The_END________' > dtime.c
- X/* dtime.c - routines to do ``ARPA-style'' time structures
- X
- Xver date who remarks
- X--- ------- --- -------------------------------------------------------------
- X01B 15nov86 JP Thouroughly hacked by Jef Poskanzer.
- X01A ??????? MTR Original version from the MH 6.5 distribution, courtesy
- X of Marshall Rose.
- X
- X*/
- X
- X
- X#include "tws.h"
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <time.h>
- X#ifdef SYS5
- X#include <string.h>
- X#else SYS5
- X#include <strings.h>
- X#include <sys/timeb.h>
- X#endif SYS5
- X
- X#ifdef SYS5
- Xextern int daylight;
- Xextern long timezone;
- Xextern char *tzname[];
- X#endif SYS5
- X
- X/* */
- X
- X#define abs(a) ( a >= 0 ? a : -a )
- X
- Xchar *tw_moty[] = {
- X "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- X "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL };
- X
- Xchar *tw_dotw[] = {
- X "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", NULL };
- X
- Xchar *tw_ldotw[] = {
- X "Sunday", "Monday", "Tuesday", "Wednesday",
- X "Thursday", "Friday", "Saturday", NULL };
- X
- X/* */
- X
- Xstatic struct zone
- X {
- X char *std;
- X char *dst;
- X int shift;
- X }
- X zones[] = {
- X "GMT", "BST", 0,
- X "EST", "EDT", -5,
- X "CST", "CDT", -6,
- X "MST", NULL, -7,
- X "PST", "PDT", -8,
- X "A", NULL, -1,
- X "B", NULL, -2,
- X "C", NULL, -3,
- X "D", NULL, -4,
- X "E", NULL, -5,
- X "F", NULL, -6,
- X "G", NULL, -7,
- X "H", NULL, -8,
- X "I", NULL, -9,
- X "K", NULL, -10,
- X "L", NULL, -11,
- X "M", NULL, -12,
- X "N", NULL, 1,
- X#ifndef HUJI
- X "O", NULL, 2,
- X#else HUJI
- X "JST", "JDT", 2,
- X#endif HUJI
- X "P", NULL, 3,
- X "Q", NULL, 4,
- X "R", NULL, 5,
- X "S", NULL, 6,
- X "T", NULL, 7,
- X "U", NULL, 8,
- X "V", NULL, 9,
- X "W", NULL, 10,
- X "X", NULL, 11,
- X "Y", NULL, 12,
- X NULL };
- X
- X#define CENTURY 19
- X
- Xlong time( );
- Xstruct tm *localtime( );
- X
- X/* */
- X
- Xchar *dtimenow( )
- X {
- X long clock;
- X
- X (void) time( &clock );
- X return ( dtime( &clock ) );
- X }
- X
- X
- Xchar *
- Xdctime( tw )
- Xstruct tws *tw;
- X {
- X static char buffer[25];
- X
- X if ( tw == NULL )
- X return ( NULL );
- X
- X (void) sprintf( buffer, "%.3s %.3s %02d %02d:%02d:%02d %.4d\n",
- X tw_dotw[tw -> tw_wday], tw_moty[tw -> tw_mon], tw -> tw_mday,
- X tw -> tw_hour, tw -> tw_min, tw -> tw_sec,
- X tw -> tw_year >= 100 ? tw -> tw_year : 1900 + tw -> tw_year );
- X
- X return ( buffer );
- X }
- X
- X/* */
- X
- Xstruct tws *
- Xdtwstime( )
- X {
- X long clock;
- X
- X (void) time( &clock );
- X return ( dlocaltime( &clock ) );
- X }
- X
- X
- Xstruct tws *
- Xdlocaltime( clock )
- Xlong *clock;
- X {
- X register struct tm *tm;
- X#ifndef SYS5
- X struct timeb tb;
- X#endif not SYS5
- X static struct tws tw;
- X
- X if ( clock == NULL )
- X return ( NULL );
- X tw.tw_flags = TW_NULL;
- X
- X tm = localtime( clock );
- X tw.tw_sec = tm -> tm_sec;
- X tw.tw_min = tm -> tm_min;
- X tw.tw_hour = tm -> tm_hour;
- X tw.tw_mday = tm -> tm_mday;
- X tw.tw_mon = tm -> tm_mon;
- X tw.tw_year = tm -> tm_year;
- X tw.tw_wday = tm -> tm_wday;
- X tw.tw_yday = tm -> tm_yday;
- X if ( tm -> tm_isdst )
- X tw.tw_flags |= TW_DST;
- X#ifndef SYS5
- X ftime( &tb );
- X tw.tw_zone = -tb.timezone;
- X#else SYS5
- X tzset( );
- X tw.tw_zone = -(timezone / 60);
- X#endif SYS5
- X tw.tw_flags &= ~TW_SDAY;
- X tw.tw_flags |= TW_SEXP;
- X tw.tw_clock = *clock;
- X
- X return ( &tw );
- X }
- X
- X
- Xstruct tws *
- Xdgmtime( clock )
- Xlong *clock;
- X {
- X register struct tm *tm;
- X static struct tws tw;
- X
- X if ( clock == NULL )
- X return ( NULL );
- X tw.tw_flags = TW_NULL;
- X
- X tm = gmtime( clock );
- X tw.tw_sec = tm -> tm_sec;
- X tw.tw_min = tm -> tm_min;
- X tw.tw_hour = tm -> tm_hour;
- X tw.tw_mday = tm -> tm_mday;
- X tw.tw_mon = tm -> tm_mon;
- X tw.tw_year = tm -> tm_year;
- X tw.tw_wday = tm -> tm_wday;
- X tw.tw_yday = tm -> tm_yday;
- X if ( tm -> tm_isdst )
- X tw.tw_flags |= TW_DST;
- X tw.tw_zone = 0;
- X tw.tw_flags &= ~TW_SDAY;
- X tw.tw_flags |= TW_SEXP;
- X tw.tw_clock = *clock;
- X
- X return( &tw );
- X }
- X
- X/* */
- X
- Xchar *
- Xdasctime( tw, flags )
- Xstruct tws *tw;
- Xint flags;
- X {
- X static char buffer[80], result[80];
- X
- X if ( tw == NULL )
- X return ( NULL );
- X
- X (void) sprintf( buffer, "%02d %s %02d %02d:%02d:%02d %s",
- X tw -> tw_mday, tw_moty[tw -> tw_mon], tw -> tw_year,
- X tw -> tw_hour, tw -> tw_min, tw -> tw_sec,
- X dtimezone( tw -> tw_zone, tw -> tw_flags | flags ) );
- X
- X if ( (tw -> tw_flags & TW_SDAY) == TW_SEXP )
- X (void) sprintf( result, "%s, %s", tw_dotw[tw -> tw_wday], buffer );
- X else
- X if ( (tw -> tw_flags & TW_SDAY) == TW_SNIL )
- X (void) strcpy( result, buffer );
- X else
- X (void) sprintf( result, "%s (%s)", buffer, tw_dotw[tw -> tw_wday] );
- X
- X return ( result );
- X }
- X
- X/* */
- X
- Xchar *
- Xdtimezone( offset, flags )
- Xint offset, flags;
- X {
- X register int hours, mins;
- X register struct zone *z;
- X static char buffer[10];
- X
- X if ( offset < 0 )
- X {
- X mins = -((-offset) % 60);
- X hours = -((-offset) / 60);
- X }
- X else
- X {
- X mins = offset % 60;
- X hours = offset / 60;
- X }
- X
- X if ( !(flags & TW_ZONE) && mins == 0 )
- X for ( z = zones; z -> std; z++ )
- X if ( z -> shift == hours )
- X return ( z -> dst && (flags & TW_DST) ? z -> dst : z -> std );
- X
- X#ifdef DSTXXX
- X if ( flags & TW_DST )
- X hours += 1;
- X#endif DSTXXX
- X (void) sprintf( buffer, "%s%02d%02d",
- X offset < 0 ? "-" : "+", abs( hours ), abs( mins ) );
- X return ( buffer );
- X }
- X
- X/* */
- X
- Xvoid
- Xtwscopy( tb, tw )
- Xstruct tws *tb, *tw;
- X {
- X#ifdef notdef
- X tb -> tw_sec = tw -> tw_sec;
- X tb -> tw_min = tw -> tw_min;
- X tb -> tw_hour = tw -> tw_hour;
- X tb -> tw_mday = tw -> tw_mday;
- X tb -> tw_mon = tw -> tw_mon;
- X tb -> tw_year = tw -> tw_year;
- X tb -> tw_wday = tw -> tw_wday;
- X tb -> tw_yday = tw -> tw_yday;
- X tb -> tw_zone = tw -> tw_zone;
- X tb -> tw_clock = tw -> tw_clock;
- X tb -> tw_flags = tw -> tw_flags;
- X#else not notdef
- X *tb = *tw;
- X#endif not notdef
- X }
- X
- X
- Xint
- Xtwsort( tw1, tw2 )
- Xstruct tws *tw1, *tw2;
- X {
- X register long c1, c2;
- X
- X (void) twclock( tw1 );
- X (void) twclock( tw2 );
- X
- X return ( (c1 = tw1 -> tw_clock) > (c2 = tw2 -> tw_clock) ? 1
- X : c1 == c2 ? 0 : -1 );
- X }
- X
- X/* */
- X
- X
- X/* Julian day number of the Unix* clock's origin, 01 Jan 1970. */
- X#define JD1970 2440587L
- X
- X
- Xlong
- Xtwjuliandate( tw )
- Xstruct tws *tw;
- X {
- X register int mday, mon, year;
- X register long a, b;
- X double jd;
- X
- X if ( (mday = tw -> tw_mday) < 1 || mday > 31 ||
- X (mon = tw -> tw_mon + 1) < 1 || mon > 12 ||
- X (year = tw -> tw_year) < 1 || year > 10000 )
- X return ( -1L );
- X if ( year < 100 )
- X year += CENTURY * 100;
- X
- X if ( mon == 1 || mon == 2 )
- X {
- X --year;
- X mon += 12;
- X }
- X if ( year < 1583 )
- X return ( -1L );
- X a = year / 100;
- X b = 2 - a + a / 4;
- X b += (long) ( (double) year * 365.25 );
- X b += (long) ( 30.6001 * ( (double) mon + 1.0 ) );
- X jd = mday + b + 1720994.5;
- X return ( (long) jd );
- X }
- X
- X
- Xlong
- Xtwsubdayclock( tw )
- Xstruct tws *tw;
- X {
- X register int sec, min, hour;
- X register long result;
- X
- X if ( (sec = tw -> tw_sec) < 0 || sec > 59 ||
- X (min = tw -> tw_min) < 0 || min > 59 ||
- X (hour = tw -> tw_hour) < 0 || hour > 23 )
- X return ( -1L );
- X
- X result = ( hour * 60 + min ) * 60 + sec;
- X result -= 60 * tw -> tw_zone;
- X if ( tw -> tw_flags & TW_DST )
- X result -= 60 * 60;
- X
- X return ( result );
- X }
- X
- X
- Xlong
- Xtwclock( tw )
- Xstruct tws *tw;
- X {
- X register long jd, sdc, result;
- X
- X if ( tw -> tw_clock != 0L )
- X return ( tw -> tw_clock );
- X
- X if ( ( jd = twjuliandate( tw ) ) == -1L )
- X return ( tw -> tw_clock = -1L );
- X if ( ( sdc = twsubdayclock( tw ) ) == -1L )
- X return ( tw -> tw_clock = -1L );
- X
- X result = ( jd - JD1970 ) * 24 * 60 * 60 + sdc;
- X
- X return ( tw -> tw_clock = result );
- X }
- X
- X/* */
- X
- X/*** twsubtract - subtract tw2 from tw1, returning result in seconds
- X
- XThe point of this routine is that using twclock( tw1 ) - twclock( tw2 )
- Xwould limit you to dates after the Unix* Epoch ( 01 January 1970 ). This
- Xroutine avoids that limit. However, because the result is represented
- Xby 32 bits, it is still limited to a span of two billion seconds, which is
- Xabout 66 years.
- X
- X*/
- X
- Xlong
- Xtwsubtract( tw1, tw2 )
- Xstruct tws *tw1, *tw2;
- X {
- X register long jd1, jd2, sdc1, sdc2, result;
- X
- X if ( ( jd1 = twjuliandate( tw1 ) ) == -1L )
- X return ( 0L );
- X if ( ( sdc1 = twsubdayclock( tw1 ) ) == -1L )
- X return ( 0L );
- X
- X if ( ( jd2 = twjuliandate( tw2 ) ) == -1L )
- X return ( 0L );
- X if ( ( sdc2 = twsubdayclock( tw2 ) ) == -1L )
- X return ( 0L );
- X
- X result = ( jd1 - jd2 ) * 24 * 60 * 60 + ( sdc1 - sdc2 );
- X
- X return ( result );
- X }
- X
- X/* */
- X
- X/*
- X * Simple calculation of day of the week. Algorithm used is Zeller's
- X * congruence. Currently, we assume if tw -> tw_year < 100
- X * then the century is CENTURY.
- X */
- X
- Xset_dotw( tw )
- Xstruct tws *tw;
- X {
- X register int month, day, year, century;
- X
- X month = tw -> tw_mon - 1;
- X day = tw -> tw_mday;
- X year = tw -> tw_year % 100;
- X century = tw -> tw_year >= 100 ? tw -> tw_year / 100 : CENTURY;
- X
- X if ( month <= 0 )
- X {
- X month += 12;
- X if ( --year < 0 )
- X {
- X year += 100;
- X century--;
- X }
- X }
- X
- X tw -> tw_wday =
- X ((26 * month - 2) / 10 + day + year + year / 4
- X - 3 * century / 4 + 1) % 7;
- X
- X tw -> tw_flags &= ~TW_SDAY;
- X tw -> tw_flags |= TW_SIMP;
- X }
- X
- X
- X/* * Unix is a virus from outer space. */
- ________This_Is_The_END________
- if test `wc -c < dtime.c` -ne 9032; then
- echo 'shar: dtime.c was damaged during transit (should have been 9032 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - dtimep.lex'
- if test -f dtimep.lex; then echo 'shar: not overwriting dtimep.lex'; else
- sed 's/^X//' << '________This_Is_The_END________' > dtimep.lex
- X%e 2000
- X%p 5000
- X%n 1000
- X%a 4000
- X%START Z
- Xsun (sun(day)?)
- Xmon (mon(day)?)
- Xtue (tue(sday)?)
- Xwed (wed(nesday)?)
- Xthu (thu(rsday)?)
- Xfri (fri(day)?)
- Xsat (sat(urday)?)
- X
- XDAY ({sun}|{mon}|{tue}|{wed}|{thu}|{fri}|{sat})
- X
- Xjan (jan(uary)?)
- Xfeb (feb(ruary)?)
- Xmar (mar(ch)?)
- Xapr (apr(il)?)
- Xmay (may)
- Xjun (jun(e)?)
- Xjul (jul(y)?)
- Xaug (aug(ust)?)
- Xsep (sep(tember)?)
- Xoct (oct(ober)?)
- Xnov (nov(ember)?)
- Xdec (dec(ember)?)
- X
- XMONTH ({jan}|{feb}|{mar}|{apr}|{may}|{jun}|{jul}|{aug}|{sep}|{oct}|{nov}|{dec})
- X
- Xw ([ \t]*)
- XW ([ \t]+)
- XD ([0-9]?[0-9])
- Xd [0-9]
- X%{
- X/* dtimep.lex - routines to do ``ARPA-style'' time parsing
- X
- Xver date who remarks
- X--- ------- --- -------------------------------------------------------------
- X01B 15nov86 JP Thouroughly hacked by Jef Poskanzer.
- X01A ??????? MTR Original version from the MH 6.5 distribution, courtesy
- X of Marshall Rose.
- X
- X*/
- X
- X#include "tws.h"
- X#include <ctype.h>
- X#include <sys/types.h>
- X#include <time.h>
- X#ifdef SYS5
- X#include <string.h>
- X#else SYS5
- X#include <strings.h>
- X#include <sys/timeb.h>
- X#endif SYS5
- X
- X#ifdef SYS5
- Xextern int daylight;
- Xextern long timezone;
- Xextern char *tzname[];
- X#endif SYS5
- X
- X/*
- X * Table to convert month names to numeric month. We use the
- X * fact that the low order 5 bits of the sum of the 2nd & 3rd
- X * characters of the name is a hash with no collisions for the 12
- X * valid month names. (The mask to 5 bits maps any combination of
- X * upper and lower case into the same hash value).
- X */
- Xstatic int month_map[] = {
- X 0,
- X 6, /* 1 - Jul */
- X 3, /* 2 - Apr */
- X 5, /* 3 - Jun */
- X 0,
- X 10, /* 5 - Nov */
- X 0,
- X 1, /* 7 - Feb */
- X 11, /* 8 - Dec */
- X 0,
- X 0,
- X 0,
- X 0,
- X 0,
- X 0,
- X 0, /*15 - Jan */
- X 0,
- X 0,
- X 0,
- X 2, /*19 - Mar */
- X 0,
- X 8, /*21 - Sep */
- X 0,
- X 9, /*23 - Oct */
- X 0,
- X 0,
- X 4, /*26 - May */
- X 0,
- X 7 }; /*28 - Aug */
- X/*
- X * Same trick for day-of-week using the hash function
- X * (c1 & 7) + (c2 & 4)
- X */
- Xstatic int day_map[] = {
- X 0,
- X 0,
- X 0,
- X 6, /* 3 - Sat */
- X 4, /* 4 - Thu */
- X 0,
- X 5, /* 6 - Fri */
- X 0, /* 7 - Sun */
- X 2, /* 8 - Tue */
- X 1 /* 9 - Mon */,
- X 0,
- X 3 }; /*11 - Wed */
- X#define SETDAY tw.tw_wday= day_map[(cp[0] & 7) + (cp[1] & 4)];\
- X tw.tw_flags |= TW_SEXP;\
- X cp += 2;
- X#define SETMONTH tw.tw_mon = month_map[(cp[0] + cp[1]) & 0x1f]; gotdate++;\
- X cp += 2;\
- X SKIPD;
- X#define CVT1OR2 (i=(*cp++ - '0'), isdigit(*cp)? i*10 + (*cp++ - '0') : i)
- X#define CVT2 ( (*cp++ - '0')*10 + (*cp++ - '0') )
- X#define CVT3 ( ( (*cp++ - '0')*10 + (*cp++ - '0') )*10 + (*cp++ - '0') )
- X#define CVT4 ( ( ( (*cp++ - '0')*10 + (*cp++ - '0') )*10 + (*cp++ - '0') )*10 + (*cp++ - '0') )
- X#define SKIPD while ( ! isdigit( *cp++ ) ) ; --cp;
- X#define ZONE(x) tw.tw_zone=(x);
- X#define ZONED(x) tw.tw_zone=(x); tw.tw_flags |= TW_DST;
- X#define LC(c) (isupper( c ) ? tolower( c ) : ( c ))
- X%}
- X%%
- X%{
- Xstruct tws *
- Xdparsetime( str )
- Xchar *str;
- X {
- X register int i;
- X static struct tws tw;
- X register char *cp;
- X register int gotdate = 0;
- X#ifndef SYS5
- X struct timeb tb;
- X#endif not SYS5
- X long clock;
- X
- X start_cond = 0;
- X
- X /* Zero out the struct. */
- X bzero( (char *) &tw, sizeof tw );
- X
- X /* Set default time zone. */
- X#ifndef SYS5
- X ftime( &tb );
- X tw.tw_zone = -tb.timezone;
- X#else SYS5
- X tzset( );
- X tw.tw_zone = -(timezone / 60);
- X#endif SYS5
- X
- X for ( ; ; )
- X switch ( cp = str, lex_string( &str, start_cond ) )
- X {
- X case -1:
- X if ( ! gotdate )
- X return ( NULL );
- X tw.tw_flags |= TW_JUNK;
- X /* fall through */
- X case 0:
- X if ( tw.tw_year == 0 )
- X {
- X /* Set default year. */
- X time( &clock );
- X tw.tw_year = localtime( &clock ) -> tm_year;
- X }
- X return ( &tw );
- X
- X%}
- X{DAY}","?{w} SETDAY;
- X"("{DAY}")"(","?) cp++, SETDAY;
- X
- X{D}(("-"{D}"-")|("/"{D}"/")){D}?{d}{d}{w} {
- X#ifdef EUROPE
- X tw.tw_mday = CVT1OR2; cp++;
- X tw.tw_mon = CVT1OR2 - 1; cp++;
- X#else EUROPE
- X tw.tw_mon = CVT1OR2 - 1; cp++;
- X tw.tw_mday = CVT1OR2; cp++;
- X#endif EUROPE
- X for ( i = 0; isdigit( *cp ); )
- X i = i * 10 + (*cp++ - '0');
- X tw.tw_year = i;
- X gotdate++;
- X }
- X{D}("/"|"-"){D}{w} {
- X#ifdef EUROPE
- X tw.tw_mday = CVT1OR2; cp++;
- X tw.tw_mon = CVT1OR2 - 1;
- X#else EUROPE
- X tw.tw_mon = CVT1OR2 - 1; cp++;
- X tw.tw_mday = CVT1OR2;
- X#endif EUROPE
- X gotdate++;
- X }
- X{D}(("-"{MONTH}"-")|(" "{MONTH}" ")|({MONTH})){D}?{d}{d}({W}at)?{w} {
- X tw.tw_mday = CVT1OR2;
- X while ( ! isalpha( *cp++ ) )
- X ;
- X SETMONTH;
- X for ( i = 0; isdigit( *cp ); )
- X i = i * 10 + (*cp++ - '0');
- X tw.tw_year = i;
- X gotdate++;
- X }
- X{D}"-"?{MONTH}({W}at)?{w} {
- X tw.tw_mday = CVT1OR2;
- X while ( ! isalpha( *cp++ ) )
- X ;
- X SETMONTH;
- X gotdate++;
- X }
- X{MONTH}{W}{D}","{W}{D}?{d}{d}{w} {
- X cp++;
- X SETMONTH;
- X tw.tw_mday = CVT1OR2;
- X SKIPD;
- X for ( i = 0; isdigit( *cp ); )
- X i = i * 10 + (*cp++ - '0');
- X tw.tw_year = i;
- X gotdate++;
- X }
- X{MONTH}{W}{D}{w} {
- X cp++;
- X SETMONTH;
- X tw.tw_mday = CVT1OR2;
- X gotdate++;
- X }
- X
- X{D}:{D}:{D}({w}am)?{w} {
- X tw.tw_hour = CVT1OR2; cp++;
- X tw.tw_min = CVT1OR2; cp++;
- X tw.tw_sec = CVT1OR2;
- X BEGIN Z;
- X }
- X{D}:{D}:{D}{w}pm{w} {
- X tw.tw_hour = CVT1OR2 + 12; cp++;
- X tw.tw_min = CVT1OR2; cp++;
- X tw.tw_sec = CVT1OR2;
- X BEGIN Z;
- X }
- X{D}:{D}({w}am)?{w} {
- X tw.tw_hour = CVT1OR2; cp++;
- X tw.tw_min = CVT1OR2;
- X BEGIN Z;
- X }
- X{D}:{D}{w}pm{w} {
- X tw.tw_hour = CVT1OR2 + 12; cp++;
- X tw.tw_min = CVT1OR2;
- X BEGIN Z;
- X }
- X[0-2]{d}{d}{d}{d}{d}{w} {
- X tw.tw_hour = CVT1OR2;
- X tw.tw_min = CVT1OR2;
- X tw.tw_sec = CVT1OR2;
- X BEGIN Z;
- X }
- X[0-2]{d}{d}{d}{w} {
- X tw.tw_hour = CVT1OR2;
- X tw.tw_min = CVT1OR2;
- X BEGIN Z;
- X }
- X<Z>"-"?ut ZONE(0 * 60);
- X<Z>"-"?gmt ZONE(0 * 60);
- X<Z>"-"?jst ZONE(2 * 60);
- X<Z>"-"?jdt ZONED(2 * 60);
- X<Z>"-"?est ZONE(-5 * 60);
- X<Z>"-"?edt ZONED(-5 * 60);
- X<Z>"-"?cst ZONE(-6 * 60);
- X<Z>"-"?cdt ZONED(-6 * 60);
- X<Z>"-"?mst ZONE(-7 * 60);
- X<Z>"-"?mdt ZONED(-7 * 60);
- X<Z>"-"?pst ZONE(-8 * 60);
- X<Z>"-"?pdt ZONED(-8 * 60);
- X<Z>"-"?nst ZONE(-(3 * 60 + 30));
- X<Z>"-"?ast ZONE(-4 * 60);
- X<Z>"-"?adt ZONED(-4 * 60);
- X<Z>"-"?yst ZONE(-9 * 60);
- X<Z>"-"?ydt ZONED(-9 * 60);
- X<Z>"-"?hst ZONE(-10 * 60);
- X<Z>"-"?hdt ZONED(-10 * 60);
- X<Z>"-"?bst ZONED(-1 * 60);
- X<Z>[a-i] tw.tw_zone = 60 * (('a'-1) - LC (*cp));
- X<Z>[k-m] tw.tw_zone = 60 * ('a' - LC (*cp));
- X<Z>[n-y] tw.tw_zone = 60 * (LC (*cp) - 'm');
- X<Z>"+"[0-1]{d}{d}{d} {
- X cp++;
- X tw.tw_zone = ((cp[0] * 10 + cp[1])
- X -('0' * 10 + '0'))*60
- X +((cp[2] * 10 + cp[3])
- X -('0' * 10 + '0'));
- X#ifdef DSTXXX
- X zonehack (&tw);
- X#endif DSTXXX
- X cp += 4;
- X }
- X<Z>"-"[0-1]{d}{d}{d} {
- X cp++;
- X tw.tw_zone = (('0' * 10 + '0')
- X -(cp[0] * 10 + cp[1]))*60
- X +(('0' * 10 + '0')
- X -(cp[2] * 10 + cp[3]));
- X#ifdef DSTXXX
- X zonehack (&tw);
- X#endif DSTXXX
- X cp += 4;
- X }
- X
- X<Z>{W}{d}{d}{d}{d} {
- X SKIPD;
- X tw.tw_year = CVT4;
- X }
- X\n |
- X{W} ;
- X%%
- X
- X#ifdef DSTXXX
- Xstatic
- Xzonehack( tw )
- Xregister struct tws *tw;
- X {
- X register struct tm *tm;
- X
- X if ( twclock( tw ) == -1L )
- X return;
- X
- X tm = localtime( &tw -> tw_clock );
- X if ( tm -> tm_isdst )
- X {
- X tw -> tw_flags |= TW_DST;
- X tw -> tw_zone -= 60;
- X }
- X }
- X#endif DSTXXX
- X
- X
- X#ifdef SYS5
- X/* Not all SYS5's have bzero( ). */
- X
- Xbzero( b, length )
- Xchar *b;
- Xint length;
- X {
- X while ( length-- > 0 )
- X *b++ = 0;
- X }
- X#endif
- ________This_Is_The_END________
- if test `wc -c < dtimep.lex` -ne 7327; then
- echo 'shar: dtimep.lex was damaged during transit (should have been 7327 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - lexedit.sed'
- if test -f lexedit.sed; then echo 'shar: not overwriting lexedit.sed'; else
- sed 's/^X//' << '________This_Is_The_END________' > lexedit.sed
- X2,/^extern int yylineno;$/c\
- Xstatic int start_cond = 0;\
- X#define BEGIN start_cond =
- X/^struct yysvf \*yyestate;$/,/^extern struct yysvf yysvec/d
- X/^# define YYNEWLINE /,/^int nstr;/d
- X/^while((nstr = yylook()/,/^if(yywrap()) /d
- X/^case -1:$/,/^fprintf(yyout,"bad switch yylook /c\
- X default: return(0);
- X/^struct yysvf *yybgin = yysvec+1;$/d
- X/^int yylineno /,$d
- ________This_Is_The_END________
- if test `wc -c < lexedit.sed` -ne 356; then
- echo 'shar: lexedit.sed was damaged during transit (should have been 356 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - lexstring.c'
- if test -f lexstring.c; then echo 'shar: not overwriting lexstring.c'; else
- sed 's/^X//' << '________This_Is_The_END________' > lexstring.c
- X#include <stdio.h>
- X#include <ctype.h>
- X
- X#define YYLERR yysvec
- X#define YYTYPE int
- X#define YYLMAX 256
- X
- Xstruct yysvf {
- X struct yywork *yystoff;
- X struct yysvf *yyother;
- X int *yystops;
- X};
- X
- Xstruct yywork {
- X YYTYPE verify;
- X YYTYPE advance;
- X};
- X
- Xextern int yyvstop[];
- Xextern struct yywork yycrank[];
- Xextern struct yysvf yysvec[];
- Xextern struct yywork *yytop;
- Xextern char yymatch[];
- Xextern char yyextra[];
- X
- X#ifdef LEXDEBUG
- Xstatic int debug = 0;
- X#endif
- X
- Xlex_string( strptr, start_cond)
- X char **strptr;
- X int start_cond;
- X{
- X register struct yysvf *state, **lsp;
- X register struct yywork *tran;
- X register int ch;
- X register char *cp = *strptr;
- X register int *found;
- X struct yysvf *yylstate[YYLMAX];
- X
- X /* start off machines */
- X lsp = yylstate;
- X state = yysvec+1+start_cond;
- X for (;;){
- X#ifdef LEXDEBUG
- X if(debug)
- X fprintf(stderr,"state %d\n",state-yysvec-1);
- X#endif
- X tran = state->yystoff;
- X if(tran == yycrank)
- X /* may not be any transitions */
- X if (state->yyother == 0 ||
- X state->yyother->yystoff == yycrank)
- X break;
- X
- X ch = *cp++;
- X#ifdef ONECASE
- X if (isupper(ch) )
- X ch = tolower(ch);
- X#endif
- Xtryagain:
- X#ifdef LEXDEBUG
- X if(debug){
- X fprintf(stderr,"char ");
- X allprint(ch);
- X putchar('\n');
- X }
- X#endif
- X if ( tran > yycrank){
- X tran += ch;
- X if (tran <= yytop && tran->verify+yysvec == state){
- X if ((state = tran->advance+yysvec) == YYLERR){
- X /* error transitions */
- X --cp;
- X break;
- X }
- X *lsp++ = state;
- X goto contin;
- X }
- X
- X } else if(tran < yycrank) {
- X /* r < yycrank */
- X tran = yycrank+(yycrank-tran) + ch;
- X#ifdef LEXDEBUG
- X if (debug)
- X fprintf(stderr,"compressed state\n");
- X#endif
- X if(tran <= yytop && tran->verify+yysvec == state){
- X if ((state = tran->advance+yysvec) == YYLERR)
- X /* error transitions */
- X break;
- X
- X *lsp++ = state;
- X goto contin;
- X }
- X tran += (yymatch[ch] - ch);
- X#ifdef LEXDEBUG
- X if(debug){
- X fprintf(stderr,"try fall back character ");
- X allprint(yymatch[ch]);
- X putchar('\n');
- X }
- X#endif
- X if(tran <= yytop && tran->verify+yysvec == state){
- X if(tran->advance+yysvec == YYLERR)
- X /* error transition */
- X break;
- X
- X *lsp++ = state = tran->advance+yysvec;
- X goto contin;
- X }
- X }
- X if ((state = state->yyother) &&
- X (tran = state->yystoff) != yycrank){
- X#ifdef LEXDEBUG
- X if(debug)
- X fprintf(stderr,"fall back to state %d\n",
- X state-yysvec-1);
- X#endif
- X goto tryagain;
- X } else
- X break;
- X
- Xcontin:
- X#ifdef LEXDEBUG
- X if(debug){
- X fprintf(stderr,"state %d char ",state-yysvec-1);
- X allprint(ch);
- X putchar('\n');
- X }
- X#endif
- X ;
- X }
- X#ifdef LEXDEBUG
- X if(debug){
- X fprintf(stderr,"stopped at %d with ",*(lsp-1)-yysvec-1);
- X allprint(ch);
- X putchar('\n');
- X }
- X#endif
- X while (lsp-- > yylstate){
- X if (*lsp != 0 && (found= (*lsp)->yystops) && *found > 0){
- X if(yyextra[*found]){
- X /* must backup */
- X ch = -*found;
- X do {
- X while (*found && *found++ != ch)
- X ;
- X } while (lsp > yylstate &&
- X (found = (*--lsp)->yystops));
- X }
- X#ifdef LEXDEBUG
- X if(debug){
- X fprintf(stderr,"\nmatch ");
- X for ( cp = *strptr;
- X cp <= ((*strptr)+(lsp-yylstate));
- X cp++)
- X allprint( *cp );
- X fprintf(stderr," action %d\n",*found);
- X }
- X#endif
- X *strptr += (lsp - yylstate + 1);
- X return(*found);
- X }
- X }
- X /* the string didn't match anything - if we're looking at
- X * eos, just return 0. Otherwise, bump the string pointer
- X * and return -1.
- X */
- X#ifdef LEXDEBUG
- X if(debug)
- X fprintf(stderr,"\nno match\n");
- X#endif
- X if ( **strptr ) {
- X (*strptr)++;
- X return (-1);
- X }
- X return (0);
- X}
- X
- X#ifdef LEXDEBUG
- Xallprint(c)
- X char c;
- X{
- X if ( c < 32 ) {
- X putc( '^', stderr );
- X c += 32;
- X } else if ( c == 127 ) {
- X putc( '^', stderr );
- X c = '?';
- X }
- X putc( c, stderr );
- X}
- X#endif
- ________This_Is_The_END________
- if test `wc -c < lexstring.c` -ne 3713; then
- echo 'shar: lexstring.c was damaged during transit (should have been 3713 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - libtws.3'
- if test -f libtws.3; then echo 'shar: not overwriting libtws.3'; else
- sed 's/^X//' << '________This_Is_The_END________' > libtws.3
- X.TH libtws 3 "08 November 1986"
- X.SH NAME
- Xlibtws \- alternate date and time routines including parsing
- X.SH SYNOPSIS
- X.nf
- X.fc ^ ~
- X.ta \w'char *dtimezone( offset, flags ); 'u
- Xinclude "tws.h"
- X.PP
- X^struct tws *dlocaltime( clock );~^/* local clock into tws */
- Xlong *clock;
- X.PP
- X^struct tws *gmtime( clock );~^/* GMT clock into tws */
- Xlong *clock;
- X.PP
- X^char *dtime( clock );~^/* clock into string */
- Xlong *clock;
- X.PP
- X^long twclock( t );~^/* tws into clock */
- Xstruct tws *t;
- X.PP
- X^long twjuliandate( t );~^/* tws into Julian day number */
- Xstruct tws *t;
- X.PP
- X^struct tws *dparsetime( str );~^/* string into tws */
- Xchar *str;
- X.PP
- X^char *dctime( t );~^/* tws into string */
- Xstruct tws *t;
- X.PP
- X^char *dasctime( t, flags );~^/* tws into string */
- Xstruct tws *t;
- Xint flags;
- X.PP
- X^char *dtimezone( offset, flags );~^/* timezone into string */
- Xint offset, flags;
- X.PP
- X^char *dtwszone( t );~^/* tws's timezone into string */
- Xstruct tws *t;
- X.PP
- X^char *dtimemow( );~^/* current time into string */
- X.PP
- X^struct tws *dtwstime( );~^/* current time into tws */
- X.PP
- X^void twscopy( tot, fromt );~^/* copy a tws */
- Xstruct tws *tot, *fromt;
- X.PP
- X^int twsort( t1, t2 );~^/* compare two tws's */
- Xstruct tws *t1, *t2;
- X.PP
- X^long twsubtract( t1, t2 );~^/* seconds between t2 and t1 */
- Xstruct tws *t1, *t2;
- X.fi
- X.SH DESCRIPTION
- X.I Libtws
- Xis a fairly complete date/time library.
- XUnlike the standard Unix* date/time routines,
- X.I libtws
- Xwill parse date/time strings into internal form.
- XThe format for specifying date/time strings is pretty loose - basically
- Xthe same as the format for date/times in network mail.
- X.PP
- XMost of the routines do not use the Unix* "clock" time
- Xformat, and therefore are not limited to dates after 01 January 1970.
- XIn particular, twsubtract() lets you subtract two dates without
- Xconverting them to "clock" form.
- X.SH "SEE\ ALSO"
- X.IR ctime(3),
- X.IR time(3)
- X.SH AUTHOR
- XMost of
- X.I libtws
- Xcame from version 6.5 of the MH message
- Xhandling system, courtesy of Marshall Rose.
- XSome improvements (?) were added by Jef Poskanzer.
- X.SH BUGS
- XThe return values point to static data whose contents are overwritten
- Xby the next call.
- X.PP
- XThe basic Unix* time format (clock) only goes back to 1970, limiting
- Xapplications somewhat.
- X.SH NOTE
- X* Unix is a virus from outer space.
- ________This_Is_The_END________
- if test `wc -c < libtws.3` -ne 2241; then
- echo 'shar: libtws.3 was damaged during transit (should have been 2241 bytes)'
- fi
- fi ; : end of overwriting check
- echo 'x - marc.c'
- if test -f marc.c; then echo 'shar: not overwriting marc.c'; else
- sed 's/^X//' << '________This_Is_The_END________' > marc.c
- X/*
- X * $Header: marc.c,v 1.2 88/06/06 01:05:02 hyc Locked $
- X */
- X
- X/* MARC - Archive merge utility
- X
- X Version 5.21, created on 04/22/87 at 15:05:10
- X
- X(C) COPYRIGHT 1985-87 by System Enhancement Associates; ALL RIGHTS RESERVED
- X
- X By: Thom Henderson
- X
- X Description:
- X This program is used to "merge" archives. That is, to move
- X files from one archive to another with no data conversion.
- X Please refer to the ARC source for a description of archives
- X and archive formats.
- X
- X Instructions:
- X Run this program with no arguments for complete instructions.
- X
- X Language:
- X Computer Innovations Optimizing C86
- X*/
- X#include <stdio.h>
- X#include "arc.h"
- X
- XFILE *src; /* source archive */
- Xchar srcname[STRLEN]; /* source archive name */
- X
- Xstatic char **lst; /* files list */
- Xstatic int lnum; /* length of files list */
- X
- X
- Xmain(nargs,arg) /* system entry point */
- Xint nargs; /* number of arguments */
- Xchar *arg[]; /* pointers to arguments */
- X{
- X char *makefnam(); /* filename fixup routine */
- X char *calloc(); /* memory manager */
- X char *envfind();
- X#if !MTS
- X char *arctemp2, *mktemp(); /* temp file stuff */
- X#endif
- X#if GEMDOS
- X void exitpause();
- X#endif
- X int n; /* index */
- X
- X if(nargs<3)
- X { printf("MARC - Archive merger, Version 5.21, created on 04/22/87 at 15:05:10\n");
- X/* printf("(C) COPYRIGHT 1985,86,87 by System Enhancement Associates;");
- X printf(" ALL RIGHTS RESERVED\n\n");
- X printf("Please refer all inquiries to:\n\n");
- X printf(" System Enhancement Associates\n");
- X printf(" 21 New Street, Wayne NJ 07470\n\n");
- X printf("You may copy and distribute this program freely,");
- X printf(" provided that:\n");
- X printf(" 1) No fee is charged for such copying and");
- X printf(" distribution, and\n");
- X printf(" 2) It is distributed ONLY in its original,");
- X printf(" unmodified state.\n\n");
- X printf("If you like this program, and find it of use, then your");
- X printf(" contribution will\n");
- X printf("be appreciated. You may not use this product in a");
- X printf(" commercial environment\n");
- X printf("or a governmental organization without paying a license");
- X printf(" fee of $35. Site\n");
- X printf("licenses and commercial distribution licenses are");
- X printf(" available. A program\n");
- X printf("disk and printed documentation are available for $50.\n");
- X printf("\nIf you fail to abide by the terms of this license, ");
- X printf(" then your conscience\n");
- X printf("will haunt you for the rest of your life.\n\n");
- X*/
- X printf("Usage: MARC <tgtarc> <srcarc> [<filename> . . .]\n");
- X printf("Where: <tgtarc> is the archive to add files to,\n");
- X printf(" <srcarc> is the archive to get files from, and\n");
- X printf(" <filename> is zero or more file names to get.\n");
- X printf("\nAdapted from MSDOS by Howard Chu\n");
- X#if GEMDOS
- X exitpause();
- X#endif
- X return 1;
- X }
- X
- X /* see where temp files go */
- X#if !MTS
- X arctemp = calloc(1, STRLEN);
- X if (!(arctemp2 = envfind("ARCTEMP")))
- X arctemp2 = envfind("TMPDIR");
- X if (arctemp2) {
- X strcpy(arctemp, arctemp2);
- X n = strlen(arctemp);
- X if (arctemp[n - 1] != CUTOFF)
- X arctemp[n] = CUTOFF;
- X }
- X#if !MSDOS
- X strcat(arctemp, mktemp("AXXXXXX"));
- X#else
- X strcat(arctemp, "$ARCTEMP");
- X#endif
- X#else
- X guinfo("SHFSEP ", gotinf);
- X sepchr[0] = gotinf[0];
- X guinfo("SCRFCHAR", gotinf);
- X tmpchr[0] = gotinf[0];
- X arctemp = "-$$$";
- X arctemp[0] = tmpchr[0];
- X#endif
- X
- X makefnam(arg[1],".arc",arcname); /* fix up archive names */
- X makefnam(arg[2],".arc",srcname);
- X/* makefnam(".$$$",arcname,newname);*/
- X sprintf(newname,"%s.arc",arctemp);
- X
- X#if !UNIX
- X upper(arcname); upper(srcname); upper(newname);
- X#endif
- X
- X arc = fopen(arcname,"rb"); /* open the archives */
- X if(!(src=fopen(srcname,"rb")))
- X abort("Cannot read source archive %s",srcname);
- X if(!(new=fopen(newname,"wb")))
- X abort("Cannot create new archive %s",newname);
- X
- X if(!arc)
- X printf("Creating new archive %s\n",arcname);
- X
- X /* get the files list set up */
- X
- X lnum = nargs-3; /* initial length of list */
- X if(lnum<1) /* phoney for default case */
- X { lnum = 1;
- X lst = (char **) calloc(1,sizeof(char *));
- X lst[0] = "*.*";
- X }
- X else /* else use filenames given */
- X { lst = (char **) calloc(lnum,sizeof(char *));
- X for(n=3; n<nargs; n++)
- X lst[n-3] = arg[n];
- X
- X for(n=0; n<lnum; ) /* expand indirect references */
- X { if(*lst[n] == '@')
- X expandlst(n);
- X else n++;
- X }
- X }
- X
- X merge(lnum,lst); /* merge desired files */
- X
- X if(arc) fclose(arc); /* close the archives */
- X fclose(src);
- X fclose(new);
- X
- X if(arc) /* make the switch */
- X if(unlink(arcname))
- X abort("Unable to delete old copy of %s",arcname);
- X if(move(newname,arcname))
- X abort("Unable to rename %s to %s",newname,arcname);
- X
- X setstamp(arcname,arcdate,arctime); /* new arc matches newest file */
- X
- X#if GEMDOS
- X exitpause();
- X#endif
- X return nerrs;
- X}
- X
- Xmerge(nargs,arg) /* merge two archives */
- Xint nargs; /* number of filename templates */
- Xchar *arg[]; /* pointers to names */
- X{
- X struct heads srch; /* source archive header */
- X struct heads arch; /* target archive header */
- X int gotsrc, gotarc; /* archive entry versions (0=end) */
- X int copy; /* true to copy file from source */
- X int n; /* index */
- X
- X gotsrc = gethdr(src,&srch); /* get first source file */
- X gotarc = gethdr(arc,&arch); /* get first target file */
- X
- X while(gotsrc || gotarc) /* while more to merge */
- X { if(strcmp(srch.name,arch.name)>0)
- X { copyfile(arc,&arch,gotarc);
- X gotarc = gethdr(arc,&arch);
- X }
- X
- X else if(strcmp(srch.name,arch.name)<0)
- X { copy = 0;
- X for(n=0; n<nargs; n++)
- X { if(match(srch.name,arg[n]))
- X { copy = 1;
- X break;
- X }
- X }
- X if(copy) /* select source or target */
- X { printf("Adding file: %s\n",srch.name);
- X copyfile(src,&srch,gotsrc);
- X }
- X else fseek(src,srch.size,1);
- X gotsrc = gethdr(src,&srch);
- X }
- X
- X else /* duplicate names */
- X { copy = 0;
- X { if((srch.date>arch.date)
- X || (srch.date==arch.date && srch.time>arch.time))
- X { for(n=0; n<nargs; n++)
- X { if(match(srch.name,arg[n]))
- X { copy = 1;
- X break;
- X }
- X }
- X }
- X }
- X if(copy) /* select source or target */
- X { printf("Updating file: %s\n",srch.name);
- X copyfile(src,&srch,gotsrc);
- X gotsrc = gethdr(src,&srch);
- X if(gotarc)
- X { fseek(arc,arch.size,1);
- X gotarc = gethdr(arc,&arch);
- X }
- X }
- X else
- X { copyfile(arc,&arch,gotarc);
- X gotarc = gethdr(arc,&arch);
- X if(gotsrc)
- X { fseek(src,srch.size,1);
- X gotsrc = gethdr(src,&srch);
- X }
- X }
- X }
- X }
- X
- X hdrver = 0; /* end of archive marker */
- X writehdr(&arch,new); /* mark the end of the archive */
- X}
- X
- Xint gethdr(f,hdr) /* special read header for merge */
- XFILE *f; /* file to read from */
- Xstruct heads *hdr; /* storage for header */
- X{
- X char *i = hdr->name; /* string index */
- X int n; /* index */
- X
- X for(n=0; n<FNLEN; n++) /* fill name field */
- X *i++ = 0176; /* impossible high value */
- X *--i = '\0'; /* properly end the name */
- X
- X hdrver = 0; /* reset header version */
- X if(readhdr(hdr,f)) /* use normal reading logic */
- X return hdrver; /* return the version */
- X else return 0; /* or fake end of archive */
- X}
- X
- Xcopyfile(f,hdr,ver) /* copy a file from an archive */
- XFILE *f; /* archive to copy from */
- Xstruct heads *hdr; /* header data for file */
- Xint ver; /* header version */
- X{
- X hdrver = ver; /* set header version */
- X writehdr(hdr,new); /* write out the header */
- X filecopy(f,new,hdr->size); /* copy over the data */
- X}
- X
- Xstatic expandlst(n) /* expand an indirect reference */
- Xint n; /* number of entry to expand */
- X{
- X FILE *lf, *fopen(); /* list file, opener */
- X char *malloc(), *realloc(); /* memory managers */
- X char buf[100]; /* input buffer */
- X int x; /* index */
- X char *p = lst[n]+1; /* filename pointer */
- X
- X if(*p) /* use name if one was given */
- X { makefnam(p,".CMD",buf);
- X upper(buf);
- X if(!(lf=fopen(buf,"r")))
- X abort("Cannot read list of files in %s",buf);
- X }
- X else lf = stdin; /* else use standard input */
- X
- X for(x=n+1; x<lnum; x++) /* drop reference from the list */
- X lst[x-1] = lst[x];
- X lnum--;
- X
- X while(fscanf(lf,"%99s",buf)>0) /* read in the list */
- X { if(!(lst=(char **) realloc(lst,(lnum+1)*sizeof(char *))))
- X abort("too many file references");
- X
- X lst[lnum] = malloc(strlen(buf)+1);
- X strcpy(lst[lnum],buf); /* save the name */
- X lnum++;
- X }
- X
- X if(lf!=stdin) /* avoid closing standard input */
- X fclose(lf);
- X}
- ________This_Is_The_END________
- if test `wc -c < marc.c` -ne 9053; then
- echo 'shar: marc.c was damaged during transit (should have been 9053 bytes)'
- fi
- fi ; : end of overwriting check
- exit 0
-
- --
- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
-
-